home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / Pascal / source / NIH Image V1.54 Source / Camera.p < prev    next >
Encoding:
Text File  |  1993-11-19  |  34.6 KB  |  1,285 lines  |  [TEXT/PJMM]

  1. unit Camera;
  2.  
  3. {Routines used by the Image program for supporting the Data Translation}
  4. {QuickCapture card, the Scion Image 1000, and the Scion LG-3.}
  5.  
  6. interface
  7.  
  8.  
  9.     uses
  10.         QuickDraw, Palettes, PrintTraps, globals, Utilities, Graphics, File1, Analysis;
  11.  
  12.  
  13.     procedure AverageFrames;
  14.     procedure GetFrame;
  15.     procedure CaptureAndDisplayFrame;
  16.     procedure HighlightPixels;
  17.     procedure ShowTriggerMessage;
  18.     procedure StartDigitizing;
  19.     procedure StopDigitizing;
  20.     procedure SetVideoChannel;
  21.     function GetFGPixel (h, v: integer): integer;
  22.     procedure CopyOffscreen (src, dst: PixMapHandle; sRect, dRect: rect);
  23.     procedure GetScionFrame (DisplayPoint: point);
  24.     procedure WaitForTrigger;
  25.     procedure ShowChannel;
  26.     procedure ShowVideoControl;
  27.     procedure UpdateVideoControl;
  28.     procedure DoVideoControl (item: integer);
  29.  
  30.  
  31.  
  32. implementation
  33.  
  34.     type
  35.         IntPtr = ^integer;
  36.  
  37.     var
  38.         SavePicBaseAddr: ptr;
  39.         StopFlagLoc: IntPtr;
  40.  
  41.  
  42.     procedure CorrectShadingOfLine (PicPtr, BFPtr: ptr; width, BFMean: integer);
  43. {}
  44. {VAR}
  45. {  PicLine,BFLine:LinePtr;}
  46. {  i,value:integer;}
  47. {BEGIN}
  48. {  PicLine:=LinePtr(PicPtr);}
  49. {  BFLine:=LinePtr(BFPtr);}
  50. {  FOR i:=0 TO width-1 DO BEGIN}
  51. {    value:=PicLine^[i];}
  52. {    value:=255-value;}
  53. {    value:=(LongInt(value)*BFMean+(BFLine^[i] DIV 2)) DIV BFLine^[i];}
  54. {    IF value>254 THEN value:=254;}
  55. {    IF value<1 THEN value:=1;}
  56. {    PicLine^[i]:=255-value;}
  57. {  END;}
  58. {  }
  59.   {a0=data pointer}
  60.   {a1=blank field data pointer}
  61.   {d0=count}
  62.   {d1=pixel value}
  63.   {d2=blank field pixel value}
  64.   {d3=blank field mean}
  65.   {d4=temp}
  66.   {d5=max pixel value(245)}
  67.   {d6=min pixel value(1)}
  68.     inline
  69.         $4E56, $0000, {   link    a6,#0}
  70.         $48E7, $FEC0, {   movem.l    a0-a1/d0-d6,-(sp)}
  71.         $206E, $000C, {   move.l    12(a6),a0}
  72.         $226E, $0008, {   move.l    8(a6),a1}
  73.         $4280,       {   clr.l    d0}
  74.         $302E, $0006, {   move.w    6(a6),d0}
  75.         $362E, $0004, {   move.w    4(a6),d3}
  76.         $2A3C, $0000, $00FE, {   move.l    #254,d5}
  77.         $2C3C, $0000, $0001, {   move.l    #1,d6}
  78.         $5380,       {   subq.l    #1,d0}
  79.         $4281,       {   clr.l    d1}
  80.         $4282,       {   clr.l    d2}
  81.         $1210,       {L1    move.b    (a0),d1}
  82.         $1419,       {   move.b    (a1)+,d2}
  83.         $4601,       {   not.b    d1}
  84.         $C2C3,       {   mulu.w    d3,d1}
  85.         $2802,       {   move.l    d2,d4}
  86.         $E244,       {   asr.w    #1,d4}
  87.         $D284,       {   add.l    d4,d1}
  88.         $82C2,       {   divu.w    d2,d1}
  89.         $B245,       {   cmp.w    d5,d1}
  90.         $6F02,       {   ble.s    L2}
  91.         $3205,       {   move.w    d5,d1}
  92.         $B246,       {L2    cmp.w    d6,d1}
  93.         $6C02,       {   bge.s    L3}
  94.         $3206,       {   move.w    d6,d1}
  95.         $4601,       {L3    not.b    d1}
  96.         $10C1,       {   move.b    d1,(a0)+}
  97.         $51C8, $FFDE, {   dbra    d0,L1}
  98.         $4CDF, $037F, {   movem.l    (sp)+,a0-a1/d0-d6}
  99.         $4E5E,       {   unlk    a6}
  100.         $DEFC, $000C; {   add.w    #12,sp}
  101. {END;}
  102.  
  103.  
  104.     procedure CorrectShading;
  105.         var
  106.             i: integer;
  107.             offset: LongInt;
  108.             p1, p2: ptr;
  109.             str: str255;
  110.     begin
  111.         with info^ do begin
  112.                 if ImageSize <> BlankFieldInfo^.ImageSize then begin
  113.                         beep;
  114.                         exit(CorrectShading);
  115.                     end;
  116.                 ShowWatch;
  117.                 p1 := PicBaseAddr;
  118.                 p2 := BlankFieldInfo^.PicBaseAddr;
  119.                 for i := 1 to nLines do begin
  120.                         CorrectShadingOfLine(p1, p2, PixelsPerLine, BlankFieldMean);
  121.                         p1 := ptr(ord4(p1) + info^.BytesPerRow);
  122.                         p2 := ptr(ord4(p2) + BlankFieldInfo^.BytesPerRow);
  123.                         if i mod 96 = 0 then
  124.                             UpdatePicWindow;
  125.                     end;
  126.                 UpdatePicWindow;
  127.                 str := title;
  128.                 if SpatiallyCalibrated then
  129.                     str := concat(str, chr($13)); {Black Diamond}
  130.                 if DensityCalibrated then
  131.                     str := concat(str, '');
  132.                 if wptr <> nil then
  133.                     SetWTitle(wptr, concat(str, '(Corrected)'));
  134.             end;
  135.     end;
  136.  
  137.  
  138.     procedure CopyOffscreen (src, dst: PixMapHandle; sRect, dRect: rect);
  139.     begin
  140.         hlock(handle(src));
  141.         hlock(handle(dst));
  142.         CopyBits(BitMapHandle(src)^^, BitMapHandle(dst)^^, sRect, dRect, SrcCopy, nil);
  143.         hunlock(handle(src));
  144.         hunlock(handle(dst));
  145.     end;
  146.  
  147.  
  148.     procedure StopDigitizing;
  149.     begin
  150.         if digitizing then
  151.             with info^ do begin
  152.                     ShowFrameRate('', fgStartTicks, fgFrameCount);
  153.                     CopyOffscreen(fgPort^.portPixMap, osPort^.portPixMap, PicRect, PicRect);
  154.                     SetItem(SpecialMenuH, StartItem, 'Start Capturing');
  155.                     Digitizing := false;
  156.                     ContinuousHistogram := false;
  157.                     with info^ do
  158.                         if PictureType = FrameGrabberType then begin
  159.                                 title := 'Camera';
  160.                                 UpdateTitleBar;
  161.                                 if HighlightSaturatedPixels then
  162.                                     LoadLUT(ctable);
  163.                             end;
  164.                     if (BlankFieldInfo <> nil) and not OptionKeyDown then
  165.                         CorrectShading;
  166.                 end;
  167.     end;
  168.  
  169.  
  170.     procedure GetFrame;
  171.         var
  172.             ticks, timeout: LongInt;
  173.     begin
  174.         if FrameGrabber = ScionLG3 then begin
  175.                 if ExternalTrigger then begin {Wait for trigger}
  176.                         ControlReg^ := $90;
  177.                         repeat
  178.                             if button then
  179.                                 ExternalTrigger := false;
  180.                         until (BitAnd(ControlReg^, $80) = $80) or not ExternalTrigger;
  181.                         ControlReg^ := 0;
  182.                         if Digitizing then
  183.                             StopDigitizing;
  184.                         UpdateVideoControl;
  185.                     end {if External Trigger}
  186.                 else begin
  187.                         TimeOut := TickCount + 30;  {1/2sec. timeout}
  188.                         ControlReg^ := $80; {Start frame capture}
  189.                         while BitAnd(ControlReg^, $80) = 0 do begin    {Wait for it to complete}
  190.                                 if TickCount > TimeOut then begin
  191.                                         ControlReg^ := 0;
  192.                                         leave
  193.                                     end;
  194.                             end;
  195.                         ControlReg^ := 0;
  196.                     end;
  197.             end
  198.         else begin {QuickCapture}
  199.                 if ExternalTrigger then begin {Wait for trigger}
  200.                         ControlReg^ := BitAnd($82, 255);
  201.                         repeat
  202.                             if button then
  203.                                 ExternalTrigger := false;
  204.                         until (ControlReg^ >= 0) or not ExternalTrigger;
  205.                         if Digitizing then
  206.                             StopDigitizing;
  207.                         UpdateVideoControl;
  208.                     end {if External Trigger}
  209.                 else begin
  210.                         TimeOut := TickCount + 30;  {1/2sec. timeout}
  211.                         ControlReg^ := BitAnd($80, 255); {Start frame capture}
  212.                         while ControlReg^ < 0 do begin    {Wait for it to complete}
  213.                                 if TickCount > TimeOut then
  214.                                     leave
  215.                             end;
  216.                     end;
  217.             end; {QuickCapture}
  218.         fgFrameCount := fgFrameCount + 1;
  219.     end;
  220.  
  221.  
  222.     procedure CaptureAndDisplayFrame;
  223.         var
  224.             tPort: GrafPtr;
  225.     begin
  226.         with info^ do begin
  227.                 if (PictureType <> FrameGrabberType) or (PixelsPerLine <> fgWidth) or (nlines <> fgHeight) then begin
  228.                         Digitizing := false;
  229.                         exit(CaptureAndDisplayFrame);
  230.                     end;
  231.                 GetFrame;
  232.                 getPort(tPort);
  233.                 SetPort(wptr);
  234.                 hlock(handle(fgPort^.portPixMap));
  235.                 hlock(handle(CGrafPort(wptr^).PortPixMap));
  236.                 CopyBits(BitMapHandle(fgPort^.portPixMap)^^, BitMapHandle(CGrafPort(wptr^).PortPixMap)^^, SrcRect, wrect, SrcCopy, nil);
  237.                 hunlock(handle(fgPort^.portPixMap));
  238.                 hunlock(handle(CGrafPort(wptr^).PortPixMap));
  239.                 SetPort(tPort);
  240.             end;
  241.     end;
  242.  
  243.  
  244.     procedure SetReg (index, value: integer);
  245.         const
  246.             RegOffset = $f5fe0;
  247.         var
  248.             reg: ptr;
  249.     begin
  250.         reg := ptr(fgSlotBase + RegOffset + index * 4);
  251.         reg^ := value;
  252.     end;
  253.  
  254.  
  255.     procedure ResetScion (GrabRect: rect; DisplayPoint: point);
  256.         const
  257.             ilutOffset = $f0000;
  258.             LineStartsRamOffset = $f4000;
  259.         type
  260.             LineStartsArray = packed array[0..8191] of UnsignedByte;
  261.             LineStartsType = ^LineStartsArray;
  262.         var
  263.             ScreenRowBytesx2: LongInt;
  264.             LutPtr: ptr;
  265.             LineStarts: LineStartsType;
  266.             EvenStart, OddStart: LongInt;
  267.             width, height, IndexOdd, IndexEven, index, i: integer;
  268.             hstart, vstart: integer;
  269.     begin
  270.         ScreenRowBytesx2 := ScreenRowBytes * 2;
  271.         LoadInputLUT(Ptr(fgSlotBase + ilutOffset));
  272.         with GrabRect, DisplayPoint do begin
  273.                 hstart := BitAnd(left, $fffc);
  274.                 vstart := BitAnd(top, $fffe);
  275.                 width := right - left;
  276.                 height := bottom - top;
  277.                 StopFlagLoc := IntPtr(LongInt(ScreenBase) + h + ScreenRowBytes * (v + height - 2) + 4);
  278.                 EvenStart := LongInt(ScreenBase) + h + ScreenRowBytes * v;
  279.                 OddStart := EvenStart + ScreenRowBytes;
  280.                 IndexOdd := 0;
  281.                 IndexEven := (height div 2) * 16;
  282.             end;
  283.         LineStarts := LineStartsType(fgSlotBase + LineStartsRamOffset);
  284.         for i := 1 to height div 2 do begin
  285.                 LineStarts^[IndexOdd] := BSR(BitAnd(OddStart, $ff000000), 24);
  286.                 LineStarts^[IndexOdd + 4] := BSR(BitAnd(OddStart, $ff0000), 16);
  287.                 LineStarts^[IndexOdd + 8] := BSR(BitAnd(OddStart, $ff00), 8);
  288.                 LineStarts^[IndexOdd + 12] := BitAnd(OddStart, $fc);
  289.                 LineStarts^[IndexEven] := BSR(BitAnd(EvenStart, $ff000000), 24);
  290.                 LineStarts^[IndexEven + 4] := BSR(BitAnd(EvenStart, $ff0000), 16);
  291.                 LineStarts^[IndexEven + 8] := BSR(BitAnd(EvenStart, $ff00), 8);
  292.                 LineStarts^[IndexEven + 12] := BitAnd(EvenStart, $fc);
  293.                 IndexOdd := IndexOdd + 16;
  294.                 IndexEven := IndexEven + 16;
  295.                 OddStart := OddStart + ScreenRowBytesx2;
  296.                 EvenStart := EvenStart + ScreenRowBytesx2;
  297.             end;
  298.         Index := height * 16;
  299.         LineStarts^[Index] := 0;
  300.         LineStarts^[Index + 4] := 0;
  301.         LineStarts^[Index + 8] := 0;
  302.         LineStarts^[Index + 12] := 1;
  303.         SetReg(1, 0);
  304.         SetReg(2, 162 - (width div 4));
  305.         SetReg(3, 0);
  306.         SetReg(4, 225 - (hstart div 4));
  307.         SetReg(5, 255 - (width div 4));
  308.         SetReg(6, 241 - (vstart div 2));
  309.         SetReg(7, 255 - (height div 2));
  310.     end;
  311.  
  312.  
  313.     procedure GetScionFrame (DisplayPoint: point);
  314.   {Captures a single Scion frame to screen memory.}
  315.         type
  316.             IntPtr = ^integer;
  317.         var
  318.             FlagLoc: IntPtr;
  319.             StartTime: LongInt;
  320.             myMMUMode: signedbyte;
  321.     begin
  322.         with DisplayPoint do
  323.             FlagLoc := IntPtr(LongInt(ScreenBase) + h + ScreenRowBytes * v + 4);
  324.         StartTime := TickCount;
  325.         myMMUMode := 1;
  326.         SwapMMUMode(myMMUMode);
  327.         FlagLoc^ := $00ff;
  328.         SetReg(1, BitOr(128, VideoChannel * 4)); {Grab Enable}
  329.         while FlagLoc^ = $00ff do
  330.             if TickCount > (StartTime + 5) then begin
  331.                     SetReg(1, 0); {Stop Grabbing}
  332.                     SwapMMUMode(myMMUMode);
  333.                     exit(GetScionFrame)
  334.                 end;
  335.         StopFlagLoc^ := $00ff;
  336.         while StopFlagLoc^ = $00ff do begin
  337.             end;
  338.         SetReg(1, 0); {Stop Grabbing}
  339.         SwapMMUMode(myMMUMode);
  340.     end;
  341.  
  342.  
  343.     function GetScreenPixel (h, v: integer): integer;
  344.         var
  345.             offset: LongInt;
  346.             p: ptr;
  347.     begin
  348.         offset := LongInt(v) * ScreenRowBytes + h;
  349.         p := ptr(ord4(ScreenBase) + offset);
  350.         GetScreenPixel := BAND(p^, 255);
  351.     end;
  352.  
  353.  
  354.     procedure CopyScionFrameOffscreen (DisplayPoint: point; wwidth, wheight: integer);
  355.         var
  356.             src, dst: ptr;
  357.             line: integer;
  358.     begin
  359.         with Info^ do begin
  360.                 with DisplayPoint do
  361.                     src := ptr(LongInt(ScreenBase) + h + ScreenRowBytes * v);
  362.                 dst := ptr(LongInt(PicBaseAddr));
  363.                 for line := 1 to wheight do begin
  364.                         BlockMove(src, dst, wwidth);
  365.                         src := ptr(ord4(src) + ScreenRowBytes);
  366.                         dst := ptr(ord4(dst) + BytesPerRow);
  367.                     end;
  368.             end;
  369.     end;
  370.  
  371.  
  372.     procedure DoMiniEventLoop (FullScreenMode: boolean);
  373.         var
  374.             loc: point;
  375.             event: EventRecord;
  376.     begin
  377.         FlushEvents(EveryEvent, 0);
  378.         if not FullScreenMode then
  379.             DrawLabels('X:', 'Y:', 'Value:');
  380.         repeat
  381.             GetMouse(loc);
  382.             LocalToGlobal(loc);
  383.             if not FullScreenMode then
  384.                 with loc do
  385.                     Show3Values(h, v, GetScreenPixel(h, v));
  386.         until WaitNextEvent(mDownMask + KeyDownMask, Event, 0, nil);
  387.     end;
  388.  
  389.  
  390.     procedure SelectCameraWindow (grabber: PicType);
  391.   {If there is a Camera window, activate it, otherwise, do nothing.}
  392.         var
  393.             i: integer;
  394.             TempInfo: InfoPtr;
  395.     begin
  396.         for i := 1 to nPics do begin
  397.                 TempInfo := pointer(WindowPeek(PicWindow[i])^.RefCon);
  398.                 if grabber = TempInfo^.PictureType then begin
  399.                         if PicWindow[i] <> nil then begin
  400.                                 if OpPending then
  401.                                     KillRoi;
  402.                                 SelectWindow(PicWindow[i]);
  403.                                 Info := TempInfo;
  404.                                 ActivateWindow;
  405.                             end; {if}
  406.                         leave;
  407.                     end; {if}
  408.             end; {for}
  409.     end;
  410.  
  411.  
  412.     procedure CaptureUsingScion;
  413.         var
  414.             GrabRect, ScreenSrcRect: rect;
  415.             DisplayPoint: point;
  416.             FullScreenMode: boolean;
  417.             wwidth, wheight: integer;
  418.             tPort: GrafPtr;
  419.             SaveBackgroundColor, hstart, vstart: integer;
  420.             ignore: integer;
  421.             mloc: point;
  422.             MainDevice: GDHandle;
  423.             SrcPixMap: PixMapHandle;
  424.             myMMUMode: signedbyte;
  425.             FlagLoc: IntPtr;
  426.             StartTime: LongInt;
  427.             grabbing: boolean;
  428.     begin
  429.         FullScreenMode := OptionKeyDown and (ScreenWidth = 640);
  430.         if FullScreenMode or (ScreenWidth > 640) then begin
  431.                 wwidth := MaxScionWidth;
  432.                 wheight := 480
  433.             end
  434.         else begin
  435.                 wwidth := 552;
  436.                 if wwidth > MaxScionWidth then
  437.                     wwidth := MaxScionWidth;
  438.                 wheight := 436;
  439.             end;
  440.         SelectCameraWindow(ScionType);
  441.         with Info^ do
  442.             if PictureType = ScionType then
  443.                 with wrect do
  444.                     if (wwidth <> right) or (wheight <> bottom) then begin
  445.                             changes := false;
  446.                             ignore := CloseAWindow(wptr);
  447.                         end;
  448.         with info^ do
  449.             if PictureType <> ScionType then begin
  450.                     if not NewPicWindow('Camera(Scion)', wwidth, wheight) then begin
  451.                             beep;
  452.                             exit(CaptureUsingScion)
  453.                         end;
  454.                 end;
  455.         KillRoi;
  456.         with info^ do begin
  457.                 PictureType := ScionType;
  458.                 changes := true;
  459.                 UpdateTitleBar;
  460.             end;
  461.         hstart := (640 - wwidth) div 2;
  462.         vstart := (480 - wheight) div 2;
  463.         SetRect(GrabRect, hstart, vstart, hstart + wwidth, vstart + wheight);
  464.         if FullScreenMode then
  465.             with DisplayPoint do begin
  466.                     h := BitAnd((640 - wwidth) div 2, $fffc);
  467.                     v := 0;
  468.                 end
  469.         else
  470.             with DisplayPoint do begin
  471.                     h := PicLeftBase;
  472.                     v := PicTopBase;
  473.                 end;
  474.         ResetScion(GrabRect, DisplayPoint);
  475.         if FullScreenMode then begin
  476.                 GetPort(tPort);
  477.                 SaveBackgroundColor := BackgroundIndex;
  478.                 SetBackgroundColor(BlackIndex);
  479.                 EraseScreen;
  480.             end;
  481.         if info^.magnification <> 1.0 then
  482.             Unzoom;
  483.         with DisplayPoint do
  484.             FlagLoc := IntPtr(LongInt(ScreenBase) + h + ScreenRowBytes * v + 4);
  485.         StartTime := TickCount;
  486.         grabbing := true;
  487.         myMMUMode := 1;
  488.         SwapMMUMode(myMMUMode);
  489.         FlagLoc^ := $00ff;
  490.         SetReg(1, BitOr(128, VideoChannel * 4)); {Grab Enable}
  491.         while FlagLoc^ = $00ff do
  492.             if TickCount > (StartTime + 5) then begin
  493.                     SetReg(1, 0); {Stop Grabbing}
  494.                     FlagLoc^ := $0000;
  495.                     SwapMMUMode(myMMUMode);
  496.                     grabbing := false;
  497.                 end;
  498.         if grabbing then begin
  499.                 SwapMMUMode(myMMUMode);
  500.                 DoMiniEventLoop(FullScreenMode);
  501.                 myMMUMode := 1;
  502.                 SwapMMUMode(myMMUMode);
  503.                 StopFlagLoc^ := $00ff;
  504.                 while StopFlagLoc^ = $00ff do begin
  505.                     end;
  506.                 SetReg(1, 0);   {Stop Grabbing}
  507.                 SwapMMUMode(myMMUMode);
  508.                 HideCursor;
  509.                 GetScionFrame(DisplayPoint);
  510.             end;
  511.         MainDevice := GetMainDevice;
  512.         SrcPixMap := MainDevice^^.gdPMap;
  513.         with DisplayPoint, ScreenSrcRect do begin
  514.                 left := h;
  515.                 top := v;
  516.                 right := left + wwidth;
  517.                 bottom := top + wheight;
  518.             end;
  519.         with info^ do begin
  520.                 CopyOffscreen(SrcPixMap, osPort^.portPixMap, ScreenSrcRect, PicRect);
  521.                 ShowCursor;
  522.                 if FullScreenMode then begin
  523.                         RestoreScreen;
  524.                         SetBackgroundColor(SaveBackgroundColor);
  525.                         SetPort(tPort);
  526.                     end;
  527.                 title := 'Camera';
  528.                 UpdateTitleBar;
  529.             end; {with}
  530.         if (BlankFieldInfo <> nil) and not OptionKeyDown then
  531.             CorrectShading;
  532.         FlushEvents(EveryEvent, 0);
  533.     end;
  534.  
  535.  
  536.     procedure HighlightPixels;
  537.         var
  538.             lut: MyCSpecArray;
  539.     begin
  540.         with info^ do begin
  541.                 lut := ctable;
  542.                 lut[1].rgb := Highlight1;
  543.                 lut[254].rgb := Highlight254;
  544.                 LoadLUT(lut);
  545.             end;
  546.     end;
  547.  
  548.  
  549.     procedure ShowTriggerMessage;
  550.     begin
  551.         if ExternalTrigger and ((FrameGrabber = QuickCapture) or (FrameGrabber = ScionLG3)) then
  552.             ShowMessage(concat('EXTERNAL TRIGGER MODE', cr, '(Press mouse button to exit)'));
  553.     end;
  554.  
  555.  
  556.     procedure StartDigitizing;
  557.         var
  558.             i, width, height: integer;
  559.             trect: rect;
  560.             NewWindow: boolean;
  561.     begin
  562.         if FrameGrabber = Scion then begin
  563.                 if HighlightSaturatedPixels then
  564.                     HighlightPixels;
  565.                 CaptureUsingScion;
  566.                 if HighlightSaturatedPixels then
  567.                     LoadLUT(info^.ctable);
  568.                 exit(StartDigitizing)
  569.             end;
  570.         if Digitizing then begin
  571.                 StopDigitizing;
  572.                 if BlankFieldInfo <> nil then
  573.                     wait(15);
  574.                 FlushEvents(EveryEvent, 0); {In case user holds key down too long}
  575.                 exit(StartDigitizing)
  576.             end;
  577.         if FrameGrabber = NoFrameGrabber then begin
  578.                 PutMessage('Capturing requires a Data Translation or SCION frame grabber card.');
  579.                 exit(StartDigitizing)
  580.             end;
  581.         if info^.PictureType <> FrameGrabberType then
  582.             SelectCameraWindow(FrameGrabberType);
  583.         NewWindow := false;
  584.         with info^ do
  585.             if (PictureType <> FrameGrabberType) or (PixelsPerLine <> fgWidth) or (nlines <> fgHeight) then begin
  586.                     if not NewPicWindow('Camera', fgWidth, fgHeight) then
  587.                         exit(StartDigitizing);
  588.                     NewWindow := true;
  589.                 end;
  590.         with info^ do begin
  591.                 PictureType := FrameGrabberType;
  592.                 if NewWindow and (not EqualRect(SrcRect, PicRect)) then {Center Frame}
  593.                     with SrcRect do begin
  594.                             width := right - left;
  595.                             height := bottom - top;
  596.                             left := (PicRect.right - width) div 2;
  597.                             right := left + width;
  598.                             top := (PicRect.bottom - height) div 2;
  599.                             bottom := top + height;
  600.                         end;
  601.                 KillRoi;
  602.                 if ScaleToFitWindow then
  603.                     ScaleToFit;
  604.                 with SrcRect do begin
  605.                         width := right - left;
  606.                         left := band(left, $fffc);
  607.                         right := left + width;
  608.                     end;
  609.                 GetWindowRect(wptr, trect);
  610.                 with trect do
  611.                     if band(left, 3) <> 0 then
  612.                         MoveWindow(wptr, band(left, $fffc), top, true); {Forces window to be word aligned}
  613.                 with SrcRect do {Prevents bus errors when Camera window moved.}
  614.                     if (top = 0) and (bottom < PicRect.bottom) then begin
  615.                             top := top + 1;
  616.                             bottom := bottom + 1;
  617.                         end;
  618.                 ResetFrameGrabber;
  619.                 Digitizing := true;
  620.                 SetItem(SpecialMenuH, StartItem, 'Stop Capturing');
  621.                 changes := true;
  622.                 BinaryPic := false;
  623.                 UpdateTitleBar;
  624.                 if HighlightSaturatedPixels then
  625.                     HighlightPixels;
  626.             end; {with info}
  627.         fgFrameCount := 0;
  628.         fgStartTicks := TickCount;
  629.         ContinuousHistogram := false;
  630.         ShowTriggerMessage;
  631.     end;
  632.  
  633.  
  634.     procedure AddLineToSum (src, dst: ptr; width: LongInt);
  635. {$IFC false}
  636.         type
  637.             SumLineType = array[0..2047] of integer;
  638.             fptr = ^SumLineType;
  639.         var
  640.             FrameLine: LinePtr;
  641.             SumLine: fptr;
  642.             i: integer;
  643.     begin
  644.         FrameLine := LinePtr(src);
  645.         SumLine := fptr(dst);
  646.         for i := 0 to width - 1 do
  647.             SumLine^[i] := SumLine^[i] + FrameLine^[i];
  648.     end;
  649. {$ENDC}
  650. inline
  651. {a0=data pointer}
  652. {a1=sum buffer pointer}
  653. {d0=count}
  654. {d1=pixel value}
  655. {d2=temp}
  656.     $4E56, $0000, {link    a6,#0}
  657.     $48E7, $E0C0, {movem.l    a0-a1/d0-d2,-(sp)}
  658.     $206E, $000C, {move.l    12(a6),a0}
  659.     $226E, $0008, {move.l    8(a6),a1}
  660.     $202E, $0004, {move.l    4(a6),d0}
  661.     $5380,              {subq.l    #1,d0}
  662.     $4281,              {clr.l    d1}
  663.     $4282,              {clr.l    d2}
  664.     $1218,              {L1    move.b    (a0)+,d1}
  665.     $3411,              {move.w    (a1),d2}
  666.     $D441,              {add.w      d1,d2}
  667.     $32C2,              {move.w    d2,(a1)+}
  668.     $51C8, $FFF6, {dbra    d0,L1}
  669.     $4CDF, $0307, {movem.l    (sp)+,a0-a1/d0-d2}
  670.     $4E5E,               {unlk    a6}
  671.     $DEFC, $000C; {add.w    #12,sp}
  672.  
  673.  
  674.  
  675. function DoAveragingOptions: boolean;
  676.     const
  677.         FramesID = 8;
  678.         VideoRateID = 9;
  679.         SumID = 10;
  680.         ShowID = 11;
  681.         FixID = 12;
  682.         MinID = 13;
  683.         MaxID = 14;
  684.     var
  685.         mylog: DialogPtr;
  686.         item, i: integer;
  687. begin
  688.     InitCursor;
  689.     mylog := GetNewDialog(140, nil, pointer(-1));
  690.     if not SumFrames then begin
  691.             ShowIntegratedValues := false;
  692.             FixIntegrationScale := false;
  693.         end;
  694.     SetDNum(MyLog, FramesID, FramesToAverage);
  695.     SetDialogItem(mylog, SumID, ord(SumFrames));
  696.     SetDialogItem(mylog, VideoRateID, ord(VideoRateAveraging));
  697.     SetDialogItem(mylog, ShowID, ord(ShowIntegratedValues));
  698.     SetDialogItem(mylog, FixID, ord(FixIntegrationScale));
  699.     SetDNum(MyLog, MinID, IntegrationMin);
  700.     SetDNum(MyLog, MaxID, IntegrationMax);
  701.     SelIText(MyLog, FramesID, 0, 32767);
  702.     repeat
  703.         ModalDialog(nil, item);
  704.         if item = FramesID then
  705.             FramesToAverage := GetDNum(MyLog, FramesID);
  706.         if item = SumID then begin
  707.                 SumFrames := not SumFrames;
  708.                 SetDialogItem(mylog, SumID, ord(SumFrames));
  709.             end;
  710.         if item = VideoRateID then begin
  711.                 VideoRateAveraging := not VideoRateAveraging;
  712.                 SetDialogItem(mylog, VideoRateID, ord(VideoRateAveraging));
  713.             end;
  714.         if item = ShowID then begin
  715.                 ShowIntegratedValues := not ShowIntegratedValues;
  716.                 SetDialogItem(mylog, ShowID, ord(ShowIntegratedValues));
  717.                 if ShowIntegratedValues then
  718.                     SumFrames := true;
  719.                 SetDialogItem(mylog, SumID, ord(SumFrames));
  720.             end;
  721.         if item = FixID then begin
  722.                 FixIntegrationScale := not FixIntegrationScale;
  723.                 SetDialogItem(mylog, FixID, ord(FixIntegrationScale));
  724.                 if FixIntegrationScale then
  725.                     SumFrames := true;
  726.                 SetDialogItem(mylog, SumID, ord(SumFrames));
  727.             end;
  728.         if (item = MinID) or (item = MaxID) then begin
  729.                 if item = MinID then
  730.                     IntegrationMin := GetDNum(MyLog, MinID)
  731.                 else
  732.                     IntegrationMax := GetDNum(MyLog, MaxID);
  733.                 SumFrames := true;
  734.                 SetDialogItem(mylog, SumID, ord(SumFrames));
  735.                 FixIntegrationScale := true;
  736.                 SetDialogItem(mylog, FixID, ord(FixIntegrationScale));
  737.             end;
  738.     until (item = ok) or (item = cancel);
  739.     DisposDialog(mylog);
  740.     if FramesToAverage < 2 then
  741.         FramesToAverage := 2;
  742.     if IntegrationMin < 0 then
  743.         IntegrationMin := 0;
  744.     if IntegrationMax > 32767 then
  745.         IntegrationMax := 32767;
  746.     if VideoRateAveraging and (item <> cancel) then begin
  747.             if FrameGrabber <> ScionLG3 then begin
  748.                     VideoRateAveraging := false;
  749.                     PutMessage('Video rate capture requires a Scion LG-3.');
  750.                     DoAveragingOptions := false;
  751.                     exit(DoAveragingOptions);
  752.                 end;
  753.             if FramesToAverage > MaxLG3Frames then begin
  754.                     FramesToAverage := MaxLG3Frames;
  755.                     DoAveragingOptions := false;
  756.                     PutMessage(concat('This ', long2str(MaxLG3Frames div 2), 'MB LG-3 can capture a maximum of ', long2str(MaxLG3Frames), ' frames at video rates.'));
  757.                     exit(DoAveragingOptions);
  758.                 end;
  759.         end;
  760.     DoAveragingOptions := item <> cancel;
  761. end;
  762.  
  763.  
  764. procedure AverageFrames;
  765.     type
  766.         IntPtr = ^integer;
  767.         SumLineType = array[0..2047] of integer;
  768.         sptr = ^SumLineType;
  769.     var
  770.         AutoSelectAll: boolean;
  771.         SelectionSize, FrameBufferSize, offset, StartTicks: LongInt;
  772.         SumBase, src, srcbase, dst, OffscreenBase: ptr;
  773.         str1, str2: str255;
  774.         xLines, xPixelsPerLine, BytesPerLine, frame, line, pixel: integer;
  775.         aline: LineType;
  776.         GrabRect: rect;
  777.         DisplayPoint: point;
  778.         hstart, vstart, wwidth, wheight: integer;
  779.         j, FramesAveraged: integer;
  780.         SrcRowBytes, DstRowBytes, i, value, MinV, MaxV, range, ActualMin, ActualMax: LongInt;
  781.         iptr: IntPtr;
  782.         FrameLine: LinePtr;
  783.         SumLine: sptr;
  784.         SaveBlankFieldInfo: InfoPtr;
  785.         myMMUMode: signedbyte;
  786. begin
  787.     with info^ do
  788.         if (PictureType <> FrameGrabberType) and (PictureType <> ScionType) then begin
  789.                 PutMessage('You must have an active Camera window(created using Start Capturing) in order to average frames.');
  790.                 macro := false;
  791.                 exit(AverageFrames)
  792.             end;
  793.     if NotRectangular or NotinBounds then begin
  794.             macro := false;
  795.             exit(AverageFrames);
  796.         end;
  797.     if (not OptionKeyWasDown) and (not macro) then begin
  798.             if not DoAveragingOptions then
  799.                 exit(AverageFrames);
  800.         end;
  801.     SaveBlankFieldInfo := BlankFieldInfo;
  802.     BlankFieldInfo := nil; {We don't want to do shading correction now}
  803.     StopDigitizing;
  804.     BlankFieldInfo := SaveBlankFieldInfo;
  805.     OptionKeyWasDown := false;
  806.     DrawLabels('Frame:', 'Total:', '');
  807.     ShowTriggerMessage;
  808.     ShowWatch;
  809.     AutoSelectAll := not Info^.RoiShowing;
  810.     if AutoSelectAll then
  811.         SelectAll(false);
  812.     with info^.RoiRect do
  813.         SelectionSize := (LongInt(right) - left) * (bottom - top);
  814.     FrameBufferSize := SelectionSize * 2;
  815.     if FrameBufferSize > BigBufSize then begin
  816.             NumToString(FrameBufferSize div 1024, str1);
  817.             NumToString(BigBufSize div 1024, str2);
  818.             str2 := concat(str1, 'K bytes are required, but only ', str2, 'K bytes are available.');
  819.             PutMessage(concat('There is not enough memory to do the requested frame averaging. ', str2));
  820.             if AutoSelectAll or (BlankFieldInfo <> nil) then
  821.                 KillRoi
  822.             else
  823.                 ShowRoi;
  824.             exit(AverageFrames)
  825.         end;
  826.     WhatToUndo := NothingToUndo;
  827.     WhatsOnClip := NothingOnClip;
  828.     SumBase := BigBuf;
  829.     case FrameGrabber of
  830.         QuickCapture:  begin
  831.                 ContinuousHistogram := false;
  832.                 ResetQuickCapture
  833.             end;
  834.         ScionLG3:  begin
  835.                 ContinuousHistogram := false;
  836.                 ResetScionLG3
  837.             end;
  838.         Scion:  begin
  839.                 with info^.wrect do begin
  840.                         wwidth := right;
  841.                         wheight := bottom;
  842.                     end;
  843.                 hstart := (640 - wwidth) div 2;
  844.                 vstart := (480 - wheight) div 2;
  845.                 SetRect(GrabRect, hstart, vstart, hstart + wwidth, vstart + wheight);
  846.                 with DisplayPoint do begin
  847.                         h := PicLeftBase;
  848.                         v := PicTopBase;
  849.                     end;
  850.                 ResetScion(GrabRect, DisplayPoint);
  851.                 HideCursor;
  852.             end;
  853.     end; {case}
  854.     with info^, info^.RoiRect do begin
  855.             offset := left + LongInt(top) * BytesPerRow;
  856.             OffscreenBase := ptr(ord4(PicBaseAddr) + offset);
  857.             if FrameGrabber = Scion then
  858.                 with DisplayPoint do begin
  859.                         BringToFront(wptr);
  860.                         offset := left + h + (v + top) * ScreenRowBytes;
  861.                         srcbase := ptr(ord4(ScreenBase) + offset);
  862.                         SrcRowBytes := ScreenRowBytes;
  863.                     end
  864.             else begin
  865.                     offset := left + LongInt(top) * fgRowBytes;
  866.                     srcbase := ptr(ord4(ptr(fgSlotBase)) + offset);
  867.                     SrcRowBytes := fgRowBytes;
  868.                 end;
  869.             xLines := bottom - top;
  870.             xPixelsPerLine := right - left;
  871.             BytesPerLine := xPixelsPerLine * 2;
  872.         end; {with}
  873.     dst := SumBase;
  874.     for line := 1 to xLines do begin {zero buffer}
  875.             BlockMove(ptr(BlankLine), dst, BytesPerLine);
  876.             dst := ptr(ord4(dst) + BytesPerLine);
  877.         end;
  878.     info^.title := 'Camera';
  879.     UpdateTitleBar;
  880.     StartTicks := TickCount;
  881.     if FrameGrabber <> ScionLG3 then
  882.         VideoRateAveraging := false;
  883.     if VideoRateAveraging then begin
  884.             if FramesToAverage > MaxLG3Frames then
  885.                 FramesToAverage := MaxLG3Frames;
  886.             ExternalTrigger := false;
  887.             BufferReg^ := 0;
  888.             GetFrame;
  889.             StartTicks := TickCount - 2;
  890.             for frame := 1 to FramesToAverage - 1 do begin
  891.                     BufferReg^ := Frame;
  892.                     GetFrame;
  893.                 end;
  894.             BufferReg^ := 0;
  895.             RealToString((TickCount - StartTicks) / 60.0, 1, 2, str1);
  896.             ShowFrameRate(concat(Long2str(FramesToAverage), ' frames', cr, str1, ' seconds', cr), StartTicks, FramesToAverage);
  897.         end;
  898.     for frame := 0 to FramesToAverage - 1 do begin
  899.             Show2Values(frame + 1, FramesToAverage);
  900.             if VideoRateAveraging then
  901.                 BufferReg^ := Frame
  902.             else begin
  903.                     if FrameGrabber = Scion then
  904.                         GetScionFrame(DisplayPoint)
  905.                     else
  906.                         GetFrame;
  907.                 end;
  908.             src := srcbase;
  909.             dst := SumBase;
  910.             myMMUMode := 1;
  911.             SwapMMUMode(myMMUMode);
  912.             for line := 1 to xLines do begin
  913.                     AddLineToSum(src, dst, xPixelsPerLine);
  914.                     src := ptr(ord4(src) + SrcRowBytes);
  915.                     dst := ptr(ord4(dst) + BytesPerLine);
  916.                 end;
  917.             SwapMMUMode(myMMUMode);
  918.             if FrameGrabber <> Scion then
  919.                 UpdateScreen(info^.RoiRect);
  920.             if CommandPeriod then begin
  921.                     beep;
  922.                     if AutoSelectAll then
  923.                         KillRoi
  924.                     else
  925.                         ShowRoi;
  926.                     exit(AverageFrames);
  927.                 end;
  928.         end; {for}
  929.     src := SumBase;
  930.     dst := OffscreenBase;
  931.     DstRowBytes := info^.BytesPerRow;
  932.     if SumFrames then begin
  933.             MinV := 2000000000;
  934.             MaxV := 0;
  935.             iptr := IntPtr(src);
  936.             for i := 1 to SelectionSize do begin
  937.                     value := iptr^;
  938.                     if value > MaxV then
  939.                         MaxV := value;
  940.                     if value < MinV then
  941.                         MinV := value;
  942.                     iptr := IntPtr(ord4(iptr) + 2);
  943.                 end;
  944.             ActualMin := MinV;
  945.             ActualMax := MaxV;
  946.             if FixIntegrationScale then begin
  947.                     MinV := IntegrationMin;
  948.                     MaxV := IntegrationMax;
  949.                 end;
  950.             range := MaxV - MinV;
  951.             if range <> 0 then
  952.                 for line := 1 to xLines do begin
  953.                         SumLine := sptr(src);
  954.                         FrameLine := LinePtr(dst);
  955.                         for j := 0 to xPixelsPerLine - 1 do begin
  956.                                 value := LongInt(SumLine^[j] - MinV) * 253 div range + 1;
  957.                                 if value < 0 then
  958.                                     value := 0;
  959.                                 if value > 255 then
  960.                                     value := 255;
  961.                                 FrameLine^[j] := value;
  962.                             end;
  963.                         src := ptr(ord4(src) + BytesPerLine);
  964.                         dst := ptr(ord4(dst) + DstRowBytes);
  965.                     end
  966.             else
  967.                 beep;
  968.         end
  969.     else
  970.         for line := 1 to xLines do begin
  971.                 SumLine := sptr(src);
  972.                 FrameLine := LinePtr(dst);
  973.                 for j := 0 to xPixelsPerLine - 1 do
  974.                     FrameLine^[j] := SumLine^[j] div FramesToAverage;
  975.                 src := ptr(ord4(src) + BytesPerLine);
  976.                 dst := ptr(ord4(dst) + DstRowBytes);
  977.             end;
  978.     if not VideoRateAveraging then begin
  979.             if SumFrames then begin
  980.                     if FixIntegrationScale then
  981.                         str1 := concat('min=', long2str(MinV), ' (', long2str(ActualMin), ')', cr, 'max=', long2str(MaxV), ' (', long2str(ActualMax), ')', cr)
  982.                     else
  983.                         str1 := concat('min=', long2str(MinV), cr, 'max=', long2str(MaxV), cr)
  984.                 end
  985.             else
  986.                 str1 := '';
  987.             RealToString((TickCount - StartTicks) / 60.0, 1, 2, str2);
  988.             ShowFrameRate(concat(Long2str(FramesToAverage), ' frames', cr, str1, str2, ' seconds', cr), StartTicks, FramesToAverage);
  989.         end;
  990.     UpdatePicWindow;
  991.     if AutoSelectAll then
  992.         KillRoi
  993.     else
  994.         ShowRoi;
  995.     if BlankFieldInfo <> nil then
  996.         CorrectShading;
  997.     if ShowIntegratedValues then
  998.         with info^ do begin
  999.                 DensityCalibrated := true;
  1000.                 fit := StraightLine;
  1001.                 nCoefficients := 2;
  1002.                 coefficient[2] := (MaxV - MinV) / 253.0;
  1003.                 coefficient[1] := MinV - coefficient[2];
  1004.                 ZeroClip := false;
  1005.                 UpdateTitleBar;
  1006.             end
  1007. end;
  1008.  
  1009.  
  1010. function GetFGPixel (h, v: integer): integer;
  1011.     var
  1012.         offset: LongInt;
  1013.         p: ptr;
  1014. begin
  1015.     with Info^ do begin
  1016.             if (h < 0) or (v < 0) or (h >= fgWidth) or (v >= fgHeight) then begin
  1017.                     GetFGPixel := WhiteIndex;
  1018.                     exit(GetFGPixel);
  1019.                 end;
  1020.             offset := LongInt(v) * fgRowBytes + h;
  1021.             if offset >= LongInt(fgHeight) * fgRowBytes then begin
  1022.                     GetFGPixel := WhiteIndex;
  1023.                     exit(GetFGPixel);
  1024.                 end;
  1025.             p := ptr(ord4(ptr(fgSlotBase)) + offset);
  1026.             GetFGPixel := BAND(p^, 255);
  1027.         end;
  1028. end;
  1029.  
  1030.  
  1031. procedure WaitForTrigger;
  1032. begin
  1033.     StopDigitizing;
  1034.     ShowWatch;
  1035.     case FrameGrabber of
  1036.         QuickCapture:  begin
  1037.                 ControlReg^ := BitAnd($82, 255);  {Wait for external trigger and capture one frame}
  1038.                 repeat
  1039.                 until (ControlReg^ >= 0) or Button;  {Wait for it to complete}
  1040.             end;
  1041.         ScionLG3:  begin
  1042.                 ControlReg^ := $90; {Wait for external trigger and capture one frame}
  1043.                 repeat
  1044.                 until (BitAnd(ControlReg^, $80) = $80) or Button;  {Wait for it to complete}
  1045.             end;
  1046.         otherwise
  1047.             repeat
  1048.             until Button;
  1049.     end;
  1050. end;
  1051.  
  1052.  
  1053. procedure SetOffset (var offset, gain: integer);
  1054. begin
  1055.     if offset < 0 then
  1056.         offset := 0;
  1057.     if offset > 255 then
  1058.         offset := 255;
  1059.     if offset > gain then
  1060.         offset := gain;
  1061.     LG3DacLow := offset;
  1062.     LG3DacHigh := LG3DacLow + (255 - gain);
  1063. end;
  1064.  
  1065.  
  1066. procedure SetGain (var offset, gain: integer);
  1067. begin
  1068.     if gain < 0 then
  1069.         gain := 0;
  1070.     if gain > 255 then
  1071.         gain := 255;
  1072.     if gain < LG3DacLow then
  1073.         gain := LG3DacLow;
  1074.     LG3DacHigh := LG3DacLow + (255 - gain);
  1075. end;
  1076.  
  1077.  
  1078. procedure ShowChannel;
  1079. begin
  1080.     SetDialogItem(VideoControl, FirstChannelID, ord(VideoChannel = 0));
  1081.     SetDialogItem(VideoControl, FirstChannelID + 1, ord(VideoChannel = 1));
  1082.     SetDialogItem(VideoControl, FirstChannelID + 2, ord(VideoChannel = 2));
  1083.     SetDialogItem(VideoControl, FirstChannelID + 3, ord(VideoChannel = 3));
  1084. end;
  1085.  
  1086.  
  1087. procedure UpdateVideoControl;
  1088. begin
  1089.     if VideoControl <> nil then
  1090.         SetDialogItem(VideoControl, TriggerID, ord(ExternalTrigger));
  1091. end;
  1092.  
  1093.  
  1094. procedure ShowOffsetAndGain (offset, gain: integer);
  1095.     var
  1096.         str: str255;
  1097. begin
  1098.     RealToString(offset, 3, 0, str);
  1099.     if str[1] = ' ' then
  1100.         str[1] := '0';
  1101.     if str[2] = ' ' then
  1102.         str[2] := '0';
  1103.     SetDString(VideoControl, OffsetID, str);
  1104.     RealToString(gain, 3, 0, str);
  1105.     if str[1] = ' ' then
  1106.         str[1] := '0';
  1107.     if str[2] = ' ' then
  1108.         str[2] := '0';
  1109.     SetDString(VideoControl, GainID, str);
  1110. end;
  1111.  
  1112.  
  1113. procedure ShowVideoControl;
  1114.     var
  1115.         gain: integer;
  1116. begin
  1117.     InitCursor;
  1118.     VideoControl := GetNewDialog(130, nil, pointer(-1));
  1119.     ShowChannel;
  1120.     SetDialogItem(VideoControl, InvertID, ord(InvertVideo));
  1121.     SetDialogItem(VideoControl, HighlightID, ord(HighlightSaturatedPixels));
  1122.     SetDialogItem(VideoControl, OscillatingID, ord(OscillatingMovies));
  1123.     SetDialogItem(VideoControl, TriggerID, ord(ExternalTrigger));
  1124.     SetDialogItem(VideoControl, BlindID, ord(BlindMovieCapture));
  1125.     SetDialogItem(VideoControl, SyncID, ord(SyncMode = SeparateSync));
  1126.     gain := 255 - (LG3DacHigh - LG3DacLow);
  1127.     ShowOffsetAndGain(LG3DacLow, gain);
  1128. end;
  1129.  
  1130.  
  1131. procedure DoVideoControl (item: integer);
  1132.     var
  1133.         i: integer;
  1134.         OutOfRange, WasDigitizing: boolean;
  1135.         offset, gain, inc, count: integer;
  1136.  
  1137.     procedure CheckFrameGrabber;
  1138.     begin
  1139.         if FrameGrabber <> ScionLG3 then begin
  1140.                 PutMessage('Programmable offset and gain are only supported on the Scion LG-3.');
  1141.                 exit(DoVideoControl);
  1142.             end;
  1143.     end;
  1144.  
  1145.     procedure SetVideoItem (item, value: integer);
  1146.     begin
  1147.         if VideoControl <> nil then
  1148.             SetDialogItem(VideoControl, item, value);
  1149.     end;
  1150.  
  1151. begin
  1152.     InitCursor;
  1153.     gain := 255 - (LG3DacHigh - LG3DacLow);
  1154.     if (item >= FirstChannelID) and (item <= (FirstChannelID + 3)) then begin
  1155.             VideoChannel := item - FirstChannelID;
  1156.             if VideoControl <> nil then
  1157.                 ShowChannel;
  1158.             if digitizing then
  1159.                 ResetFrameGrabber;
  1160.         end;
  1161.     if item = InvertID then begin
  1162.             InvertVideo := not InvertVideo;
  1163.             SetVideoItem(InvertID, ord(InvertVideo));
  1164.             if digitizing then
  1165.                 ResetFrameGrabber;
  1166.         end;
  1167.     if item = HighlightID then begin
  1168.             HighlightSaturatedPixels := not HighlightSaturatedPixels;
  1169.             SetVideoItem(HighlightID, ord(HighlightSaturatedPixels));
  1170.             if digitizing then begin
  1171.                     if HighlightSaturatedPixels then
  1172.                         HighlightPixels
  1173.                     else
  1174.                         LoadLUT(info^.ctable);
  1175.                 end;
  1176.         end;
  1177.     if item = OscillatingID then begin
  1178.             OscillatingMovies := not OscillatingMovies;
  1179.             SetVideoItem(OscillatingID, ord(OscillatingMovies));
  1180.         end;
  1181.     if item = TriggerID then begin
  1182.             ExternalTrigger := not ExternalTrigger;
  1183.             case FrameGrabber of
  1184.                 QuickCapture, ScionLG3:  begin
  1185.                         WasDigitizing := digitizing;
  1186.                         StopDigitizing;
  1187.                         if ExternalTrigger and WasDigitizing then
  1188.                             StartDigitizing;
  1189.                     end;
  1190.                 otherwise
  1191.                     ExternalTrigger := false;
  1192.             end;
  1193.             SetVideoItem(TriggerID, ord(ExternalTrigger));
  1194.         end;
  1195.     if item = BlindID then begin
  1196.             BlindMovieCapture := not BlindMovieCapture;
  1197.             SetVideoItem(BlindID, ord(BlindMovieCapture));
  1198.         end;
  1199.     if item = SyncID then begin
  1200.             if SyncMode <> SeparateSync then
  1201.                 SyncMode := SeparateSync
  1202.             else
  1203.                 SyncMode := NormalSync;
  1204.             case FrameGrabber of
  1205.                 ScionLG3: 
  1206.                     if digitizing then
  1207.                         ResetFrameGrabber;
  1208.                 QuickCapture:  begin
  1209.                         PutMessage('Sync is not under program control on the QuickCapure card.');
  1210.                         SyncMode := NormalSync;
  1211.                         macro := false;
  1212.                     end;
  1213.                 otherwise
  1214.                     ;
  1215.             end;
  1216.             SetVideoItem(SyncID, ord(SyncMode = SeparateSync));
  1217.         end;
  1218.     if (item >= OffsetUpID) and (item <= GainDownID) then begin
  1219.             CheckFrameGrabber;
  1220.             offset := LG3DacLow;
  1221.             inc := 1;
  1222.             count := 0;
  1223.             repeat
  1224.                 count := count + 1;
  1225.                 if count > 2 then
  1226.                     inc := 2;
  1227.                 if count > 4 then
  1228.                     inc := 5;
  1229.                 if count > 8 then
  1230.                     inc := 10;
  1231.                 case item of
  1232.                     OffsetUpID:  begin
  1233.                             offset := offset + inc;
  1234.                             SetOffset(offset, gain);
  1235.                         end;
  1236.                     OffsetDownID:  begin
  1237.                             offset := offset - inc;
  1238.                             SetOffset(offset, gain);
  1239.                         end;
  1240.                     GainUpID:  begin
  1241.                             gain := gain + inc;
  1242.                             SetGain(offset, gain);
  1243.                         end;
  1244.                     GainDownID:  begin
  1245.                             gain := gain - inc;
  1246.                             SetGain(offset, gain);
  1247.                         end;
  1248.                 end; {case}
  1249.                 ShowOffsetAndGain(LG3DacLow, gain);
  1250.                 if Digitizing and (count > 1) then begin
  1251.                         DacLowReg^ := LG3DacLow;
  1252.                         DacHighReg^ := LG3DacHigh;
  1253.                         CaptureAndDisplayFrame;
  1254.                         if ContinuousHistogram then begin
  1255.                                 ShowContinuousHistogram;
  1256.                                 DrawHistogram
  1257.                             end
  1258.                     end
  1259.                 else
  1260.                     wait(5);
  1261.             until not button;
  1262.         end;
  1263.     if item = ResetID then begin
  1264.             CheckFrameGrabber;
  1265.             LG3DacLow := DefaultLG3DacLow;
  1266.             LG3DacHigh := DefaultLG3DacHigh;
  1267.             gain := 255 - (LG3DacHigh - LG3DacLow);
  1268.             ParamText(long2str(LG3DacLow), long2str(gain), '', '');
  1269.             ShowOffsetAndGain(LG3DacLow, gain);
  1270.         end;
  1271.     if FramesToAverage < 2 then
  1272.         FramesToAverage := 2;
  1273.     if (FrameGrabber = Scion) and (ExternalTrigger or BlindMovieCapture) then begin
  1274.             PutMessage('External triggering and blind movie capture are not supported with the SCION frame grabber card.');
  1275.             ExternalTrigger := false;
  1276.             BlindMovieCapture := false;
  1277.         end;
  1278.     if FrameGrabber = ScionLG3 then begin
  1279.             DacLowReg^ := LG3DacLow;
  1280.             DacHighReg^ := LG3DacHigh;
  1281.         end;
  1282. end;
  1283.  
  1284.  
  1285. end.